home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / PROGRAMR / OLE2BOOK.ZIP / CHAP05.ZIP / CHAP05 / POLYLINE / IPERSTOR.CPP < prev    next >
C/C++ Source or Header  |  1993-04-13  |  9KB  |  330 lines

  1. /*
  2.  * IPERSTOR.CPP
  3.  * Modifications for Chapter 5.
  4.  *
  5.  * Implementation of the IPersistStorage interface that we expose on the
  6.  * Polyline object.
  7.  *
  8.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  9.  *
  10.  * Kraig Brockschmidt, Software Design Engineer
  11.  * Microsoft Systems Developer Relations
  12.  *
  13.  * Internet  :  kraigb@microsoft.com
  14.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  15.  */
  16.  
  17.  
  18. #include "polyline.h"
  19.  
  20.  
  21. /*
  22.  * CImpIPersistStorage:CImpIPersistStorage
  23.  * CImpIPersistStorage::~CImpIPersistStorage
  24.  *
  25.  * Constructor Parameters:
  26.  *  pObj            LPVOID pointing to the object we live in.
  27.  *  punkOuter       LPUNKNOWN of the controlling unknown.
  28.  */
  29.  
  30. CImpIPersistStorage::CImpIPersistStorage(LPVOID pObj, LPUNKNOWN punkOuter)
  31.     {
  32.     m_cRef=0;
  33.     m_pObj=pObj;
  34.     m_punkOuter=punkOuter;
  35.     return;
  36.     }
  37.  
  38.  
  39. CImpIPersistStorage::~CImpIPersistStorage(void)
  40.     {
  41.     return;
  42.     }
  43.  
  44.  
  45.  
  46.  
  47. /*
  48.  * CImpIPersistStorage::QueryInterface
  49.  * CImpIPersistStorage::AddRef
  50.  * CImpIPersistStorage::Release
  51.  *
  52.  * Purpose:
  53.  *  Standard set of IUnknown members for this interface
  54.  */
  55.  
  56. STDMETHODIMP CImpIPersistStorage::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  57.     {
  58.     return m_punkOuter->QueryInterface(riid, ppv);
  59.     }
  60.  
  61. STDMETHODIMP_(ULONG) CImpIPersistStorage::AddRef(void)
  62.     {
  63.     ++m_cRef;
  64.     return m_punkOuter->AddRef();
  65.     }
  66.  
  67. STDMETHODIMP_(ULONG) CImpIPersistStorage::Release(void)
  68.     {
  69.     --m_cRef;
  70.     return m_punkOuter->Release();
  71.     }
  72.  
  73.  
  74.  
  75.  
  76.  
  77. /*
  78.  * CImpIPersistStorage::GetClassID
  79.  *
  80.  * Purpose:
  81.  *  Returns the CLSID of the object represented by this interface.
  82.  *
  83.  * Parameters:
  84.  *  pClsID          LPCLSID in which to store our CLSID.
  85.  *
  86.  * Return Value:
  87.  *  HRESULT         NOERROR on success, error code otherwise.
  88.  */
  89.  
  90. STDMETHODIMP CImpIPersistStorage::GetClassID(LPCLSID pClsID)
  91.     {
  92.     LPCPolyline     pObj=(LPCPolyline)m_pObj;
  93.  
  94.     *pClsID=pObj->m_clsID;
  95.     return NOERROR;
  96.     }
  97.  
  98.  
  99.  
  100.  
  101.  
  102. /*
  103.  * CImpIPersistStorage::IsDirty
  104.  *
  105.  * Purpose:
  106.  *  Tells the caller if we have made changes to this object since
  107.  *  it was loaded or initialized new.
  108.  *
  109.  * Parameters:
  110.  *  None
  111.  *
  112.  * Return Value:
  113.  *  HRESULT         Contains S_OK if we ARE dirty, S_FALSE if NOT dirty,
  114.  *                  that is, "Yes I AM dirty, or NO, I'm clean."
  115.  */
  116.  
  117. STDMETHODIMP CImpIPersistStorage::IsDirty(void)
  118.     {
  119.     LPCPolyline     pObj=(LPCPolyline)m_pObj;
  120.  
  121.     return ResultFromScode(pObj->m_fDirty ? S_OK : S_FALSE);
  122.     }
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130. /*
  131.  * CImpIPersistStorage::InitNew
  132.  *
  133.  * Purpose:
  134.  *  Provides the object with the IStorage they can hold on to while
  135.  *  they are running.  Here we can initialize the structure of the
  136.  *  storage and AddRef it for incremental access.  This function will
  137.  *  only be called once in the object's lifetime in lieu of ::Load.
  138.  *
  139.  * Parameters:
  140.  *  pIStorage       LPSTORAGE for the object.
  141.  *
  142.  * Return Value:
  143.  *  HRESULT         NOERROR on success, error code otherwise.
  144.  */
  145.  
  146. STDMETHODIMP CImpIPersistStorage::InitNew(LPSTORAGE pIStorage)
  147.     {
  148.     //Nothing to do.  We don't need a storage outside ::Load and ::Save.
  149.     return NOERROR;
  150.     }
  151.  
  152.  
  153.  
  154.  
  155.  
  156. /*
  157.  * CImpIPersistStorage::Load
  158.  *
  159.  * Purpose:
  160.  *  Instructs the object to load itself from a previously saved IStorage
  161.  *  that was handled by ::Save in another object lifetime.  This function
  162.  *  will only be called once in the object's lifetime in lieu of ::InitNew.
  163.  *  The object may hold on to pIStorage here for incremental access.
  164.  *
  165.  * Parameters:
  166.  *  pIStorage       LPSTORAGE from which to load.
  167.  *
  168.  * Return Value:
  169.  *  HRESULT         NOERROR on success, error code otherwise.
  170.  */
  171.  
  172. STDMETHODIMP CImpIPersistStorage::Load(LPSTORAGE pIStorage)
  173.     {
  174.     LPCPolyline     pObj=(LPCPolyline)m_pObj;
  175.     POLYLINEDATA    pl;
  176.     ULONG           cb;
  177.     LPSTREAM        pIStream;
  178.     HRESULT         hr;
  179.  
  180.     if (NULL==pIStorage)
  181.         return ResultFromScode(STG_E_INVALIDPOINTER);
  182.  
  183.     //We don't check ClassStg to remain compatible with other chatpers.
  184.  
  185.     //Open the CONTENTS stream
  186.     hr=pIStorage->OpenStream("CONTENTS", 0, STGM_DIRECT | STGM_READ
  187.         | STGM_SHARE_EXCLUSIVE, 0, &pIStream);
  188.  
  189.     if (FAILED(hr))
  190.         return ResultFromScode(STG_E_READFAULT);
  191.  
  192.     //Read all the data into the POLYLINEDATA structure.
  193.     hr=pIStream->Read((LPVOID)&pl, CBPOLYLINEDATA, &cb);
  194.     pIStream->Release();
  195.  
  196.     if (CBPOLYLINEDATA!=cb)
  197.         return ResultFromScode(STG_E_READFAULT);
  198.  
  199.     pObj->m_pIPolyline->DataSet(&pl, TRUE, TRUE);
  200.     return NOERROR;
  201.     }
  202.  
  203.  
  204.  
  205.  
  206.  
  207. /*
  208.  * CImpIPersistStorage::Save
  209.  *
  210.  * Purpose:
  211.  *  Saves the native data for this object to an IStorage which may
  212.  *  or may not be the same as the one previously passed to
  213.  *  ::Load, indicated with fSameAsLoad.  We also cannot write anything
  214.  *  to this storage until ::SaveCompleted although we may read.
  215.  *
  216.  * Parameters:
  217.  *  pIStorage       LPSTORAGE in which to save our data.
  218.  *  fSameAsLoad     BOOL indicating if this is the same pIStorage
  219.  *                  that was passed to ::Load.  If it was, then
  220.  *                  objects that built up a structure in that storage
  221.  *                  do not have to regenerate the entire thing.
  222.  *
  223.  * Return Value:
  224.  *  HRESULT         NOERROR on success, error code otherwise.
  225.  */
  226.  
  227. STDMETHODIMP CImpIPersistStorage::Save(LPSTORAGE pIStorage, BOOL fSameAsLoad)
  228.     {
  229.     LPCPolyline     pObj=(LPCPolyline)m_pObj;
  230.     POLYLINEDATA    pl;
  231.     ULONG           cb;
  232.     LPSTREAM        pIStream;
  233.     HRESULT         hr;
  234.  
  235.     if (NULL==pIStorage)
  236.         return ResultFromScode(STG_E_INVALIDPOINTER);
  237.  
  238.     /*
  239.      * fSameAsLoad is not important to us since we always rewrite
  240.      * an entire stream as well as the identification tags for this
  241.      * object.  Note that we don't bother to check the ClassStg
  242.      * above in ::Load to remain compatible with other revisions
  243.      * of Polyline in other chapters.
  244.      */
  245.  
  246.     WriteClassStg(pIStorage, pObj->m_clsID);
  247.     WriteFmtUserTypeStg(pIStorage, pObj->m_cf, (*pObj->m_pST)[IDS_USERTYPE]);
  248.  
  249.     hr=pIStorage->CreateStream("CONTENTS", STGM_DIRECT | STGM_CREATE
  250.         | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pIStream);
  251.  
  252.     if (FAILED(hr))
  253.         return ResultFromScode(STG_E_WRITEFAULT);
  254.  
  255.     pObj->m_pIPolyline->DataGet(&pl);
  256.     hr=pIStream->Write((LPVOID)&pl, CBPOLYLINEDATA, &cb);
  257.     pIStream->Release();
  258.  
  259.     return (SUCCEEDED(hr) && CBPOLYLINEDATA==cb) ?
  260.         NOERROR : ResultFromScode(STG_E_WRITEFAULT);
  261.     }
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270. /*
  271.  * CImpIPersistStorage::SaveCompleted
  272.  *
  273.  * Purpose:
  274.  *  Notifies the object that the storage in pIStorage has been completely
  275.  *  saved now.  This is called when the user of this object wants to
  276.  *  save us in a completely new storage, and if we normally hang on to
  277.  *  the storage we have to reinitialize ourselves here for this new one
  278.  *  that is now complete.
  279.  *
  280.  * Parameters:
  281.  *  pIStorage       LPSTORAGE of the new storage in which we now live.
  282.  *
  283.  * Return Value:
  284.  *  HRESULT         NOERROR on success, error code otherwise.
  285.  */
  286.  
  287. STDMETHODIMP CImpIPersistStorage::SaveCompleted(LPSTORAGE pIStorage)
  288.     {
  289.     /*
  290.      * We have nothing to do here since we do everything in ::Load and
  291.      * ::Save.  For most objects than handle saves this way, they need
  292.      * no code here.  Other objects must release their current storage
  293.      * here and begin using the new one in pIStorage.
  294.      */
  295.  
  296.     return NOERROR;
  297.     }
  298.  
  299.  
  300.  
  301.  
  302.  
  303. /*
  304.  * CImpIPersistStorage::HandsOffStorage
  305.  *
  306.  * Purpose:
  307.  *  Instructs the object that another agent is interested in having total
  308.  *  access to the storage we might be hanging on to from ::InitNew or
  309.  *  ::SaveCompleted.  In this case we must release our hold and await
  310.  *  another call to ::SaveCompleted before we have a hold again.
  311.  *
  312.  *  Situations where this might happen arise in compound document scenarios
  313.  *  where this object might be in-place active but the application wants
  314.  *  to rename and commit the root storage.  Therefore we are